﻿using Microsoft.AspNet.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ASOFT.PRINTER
{
    public class ServerCommunicator
    {
        private string NOTIFY_METHOD_NAME = "WinNotify";
        private string STOP_METHOD_NAME = "WinStop";
        public static string CLIENT_NAME = "Win Client";

        /// <summary>
        /// Tên của client, 
        /// có thể dùng tên của máy tính, hoặc tên của user
        /// </summary>
        public string ClientName
        {
            get;
            set;
        }

        /// <summary>
        /// Delegate của hàm truyền vào sự kiện On
        /// </summary>
        /// <param name="printerName"></param>
        /// <param name="message"></param>
        public delegate void OnCommand(object commandParameter);

        /// <summary>
        /// Url của server
        /// </summary>
        public string ServerURL
        {
            get;
            private set;
        }

        /// <summary>
        /// Connection dùng chung cho các hub của client,
        /// giúp cho hub client tương tác với hub server
        /// </summary>
        public HubConnection HubConnection
        {
            get;
            set;
        }

        /// <summary>
        /// Hub proxy để tương tác với hub trên server
        /// </summary>
        public IHubProxy HubProxy
        {
            get;
            set;
        }

        /// <summary>
        /// Chuỗi GUID của client hiện tại
        /// </summary>
        public string ConnectionID
        {
            get
            {
                return HubConnection.ConnectionId; 
            }
        }

        /// <summary>
        /// Khởi tạo đối tượng ServerCommunicator
        /// </summary>
        /// <param name="url">Url của server 
        /// VD: http://localhost/ </param>
        /// <throw>404: nếu url không hợp lệ, hoặc không tồn tại</throw>
        public ServerCommunicator(string url)
        {
            //var request = (HttpWebRequest)WebRequest.Create(url);
            //request.Method = "HEAD";
            //var response = (HttpWebResponse)request.GetResponse();
            //var success = (response.StatusCode == HttpStatusCode.OK);
            //if (!success)
            //{
            //    throw new Exception(string.Format("Error 404: URL {0} not found (or invalid) ", url));
            //}
            //else
            //{
                ServerURL = url;
                HubConnection = new HubConnection(url);
            //}
        }

        /// <summary>
        /// Gán hàm xử lý sự kiện khi server gọi
        /// </summary>
        /// <param name="eventName">Tên của hàm mà server gọi
        /// VD: Clients.All.broadcastMessage(name, message);</param>
        /// <param name="onCommand">Hàm sự lý sự kiện</param>
        public void SetEventListennerOn(string eventName, OnCommand onCommand)
        {
            HubProxy.On<string>(eventName, (printerName) =>
            {
                onCommand(printerName);

            });
        }

        /// <summary>
        /// Gọi một phương thức
        /// </summary>
        /// <param name="methodName">Tên của phương thức trong class hub của server</param>
        /// <param name="parameterList">Danh sách các tham số, 
        /// số lượng phải giống số lượng các tham số của phương thức trong class hub của server</param>
        public void CallServerHubMethod(string methodName, List<object> parameterList)
        {
            HubProxy.Invoke(methodName, parameterList.ToArray());
        }

        /// <summary>
        /// Gọi một phương thức
        /// </summary>
        /// <param name="methodName">Tên của phương thức trong class hub của server</param>
        /// <param name="parameterList">Các tham số, 
        /// số lượng phải giống số lượng các tham số của phương thức trong class hub của server</param>
        public void CallServerHubMethod(string methodName, params object[] parameterList)
        {
            HubProxy.Invoke(methodName, parameterList);
        }

        /// <summary>
        /// Tạo mới một hub proxy để tương tác với hub trên server
        /// </summary>
        /// <param name="hubName">Tên của class hub trên server ( có phân biệt hoa thường )</param>
        /// <returns>Một reference tới ServerCommunicator.HubProxy,
        /// hoặc trả về null nếu không thể tạo hub</returns>
        public IHubProxy CreateHubProxy(string hubName)
        {
            try
            {
                // Tạo hub proxy
                HubProxy = HubConnection.CreateHubProxy(hubName);
                HubConnection.Start().Wait();
                // Gọi hàm notify server
                CallServerHubMethod(NOTIFY_METHOD_NAME, CLIENT_NAME);
                return HubProxy;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        /// <summary>
        /// Bắt đầu kết nối
        /// </summary>
        /// <param name="wait">nếu wait là true, thì hàm này sẽ chạy synchronous</param>
        public void StartConnection(bool wait = true)
        {
            if (wait)
            {
                HubConnection.Start();//.Wait();
                //HubProxy.Invoke(NOTIFY_METHOD_NAME, CLIENT_NAME, ConnectionID);
            }
            else
            {
                HubConnection.Start();
            }
        }

        public void StopConnection(bool wait = true)
        {
            if (wait)
            {
                HubProxy.Invoke(STOP_METHOD_NAME, CLIENT_NAME, ConnectionID);
                HubConnection.Stop();                
            }
            else
            {
                HubConnection.Stop();
            }
        }

    }
}
